package com.qijian.listener;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import com.qijian.common.core.domain.entity.SysRole;
import com.qijian.common.core.domain.entity.SysUser;
import com.qijian.common.enums.FlowableCommonEnum;
import com.qijian.common.enums.FlowableKeyEnum;
import com.qijian.common.utils.CommonUtil;
import com.qijian.common.utils.DateUtils;
import com.qijian.common.utils.ObjectUtils;
import com.qijian.common.utils.StringUtils;
import com.qijian.common.utils.mybatis.WhereEntityTool;
import com.qijian.flowable.common.cmd.AddCcIdentityLinkCmd;
import com.qijian.flowable.constant.FlowableConstant;
import com.qijian.flowable.domain.Flow;
import com.qijian.flowable.domain.FlowableRecordPower;
import com.qijian.flowable.domain.query.FlowableRecordPowerQuery;
import com.qijian.flowable.domain.vo.CcToVo;
import com.qijian.flowable.service.IFlowService;
import com.qijian.flowable.service.IFlowableRecordPowerService;
import com.qijian.flowable.util.SpringContextUtils;
import com.qijian.system.mapper.SysRoleMapper;
import com.qijian.system.mapper.SysUserMapper;
import com.qijian.system.service.ISysConfigService;
import com.qijian.system.service.ISysDictDataService;
import com.qijian.tool.domain.Msg;
import com.qijian.tool.service.IMsgService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ManagementService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Component
@Transactional
public class FlowServiceTask implements ExecutionListener, ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void notify(DelegateExecution delegateExecution) {
//        IPointOrderService pointOrderService = applicationContext.getBean(IPointOrderService.class);
        ManagementService managementService = applicationContext.getBean(ManagementService.class);
        IMsgService msgService = applicationContext.getBean(IMsgService.class);
        IFlowableRecordPowerService flowableRecordPowerService = applicationContext.getBean(IFlowableRecordPowerService.class);
        SysRoleMapper roleMapper = applicationContext.getBean(SysRoleMapper.class);
        SysUserMapper userMapper = applicationContext.getBean(SysUserMapper.class);
        HistoryService historyService = applicationContext.getBean(HistoryService.class);
        Map<String, Object> variables = delegateExecution.getVariables();
        ISysConfigService sysConfigService = applicationContext.getBean(ISysConfigService.class);
//        ISupplierService supplierService = SpringContextUtils.getBean(ISupplierService.class);
        ISysDictDataService dictDataService = SpringContextUtils.getBean(ISysDictDataService.class);
        String taskId = delegateExecution.getId();
        log.info("全局==={}", variables);
        String t = variables.get("title").toString();
        String type = variables.get("type").toString();
        final String title = t.replace("有流程到达", "流程结束");
        if (type.equals("point")) {
            String userName = variables.get("userName").toString();
            String deptName = variables.get("deptName").toString();
            String dateTime = variables.get("createTime").toString();
            String userId = variables.get("userId").toString();
            List<CcToVo> msgU = new ArrayList<>();
            List<SysUser> msgUsers = (List<SysUser>) variables.get("msgUsers");
            if (deptName.contains("轨道交通")) {
                handleCC(roleMapper, userMapper, msgU, "flw_hsry");
            }
            if (CollectionUtil.isNotEmpty(msgUsers) && CollectionUtil.isNotEmpty(msgUsers.stream().filter(e -> ObjectUtils.isNotNull(e)).collect(Collectors.toList()))) {
                msgUsers.stream().filter(e -> ObjectUtils.isNotNull(e)).forEach(e -> {
                    CcToVo ccToVo = new CcToVo();
                    ccToVo.setUserId(e.getUserId().toString());
                    ccToVo.setUserName(e.getNickName().toString());
                    msgU.add(ccToVo);
                });
                managementService.executeCommand(new AddCcIdentityLinkCmd(delegateExecution.getProcessInstanceId(), taskId,
                        "1", msgU.toArray(new CcToVo[]{})));
                addRecordPower(msgU, delegateExecution.getProcessInstanceId(), flowableRecordPowerService, null);
            }
            List<Msg> msgList = new ArrayList<>();
            variables.forEach((k, v) -> {
                if (k.indexOf("input_") > -1) {
                    if (CollectionUtil.isNotEmpty(msgU)) {
                        msgU.stream().forEach(e -> {
                            handleMsg(delegateExecution, title, v, msgList, userName, dateTime, Long.parseLong(e.getUserId()), type);
                        });
                    }
                    msgService.saveBatch(msgList, false, false);
                    //调用 生成工单以及消息服务
//                    boolean processOrder = pointOrderService.createProcessOrder((Long.parseLong(v.toString())), title, userName, dateTime, userId, delegateExecution.getProcessInstanceId());
//                    log.info("生成工单以及消息服务状态==={}", processOrder);
                }
            });


        }

    }

    private static void handleCcMsg(DelegateExecution delegateExecution, String title, Object v, List<Msg> msgList, String userName, String dateTime, Long uId, String type) {
        Msg msg1 = new Msg();
        msg1.setTitle(title);
        msg1.setSourceId(v.toString());
        msg1.setSourceType(type);
        if (type.equals(FlowableCommonEnum.flow_fin_finance_dispatch.getValue())) {
            msg1.setContent("(抄送)您收到一条新的财务派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_process_craft_dispatch.getValue())) {
            msg1.setContent("(抄送)您收到一条新的工艺派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_process_performance.getValue())) {
            msg1.setContent("(抄送)您收到一条新的工装派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_quality_craft_dispatch.getValue())) {
            msg1.setContent("(抄送)您收到一条新的质量派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_adjustOrder.getValue())) {
            msg1.setContent("(抄送)您收到一条新的核算派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_fin_cost_ex.getValue())) {
            msg1.setContent("(抄送)您收到一条新的核算异常绩效申诉消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getId());
            }
        } else if (type.equals(FlowableCommonEnum.purm_supplier_retrial.getValue())) {
            msg1.setContent("(抄送)您收到一条新的供应商复审消息");
            msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "?id=" + v);
        } else if (type.equals(FlowableCommonEnum.flow_re_knife_transfer.getValue())) {
            msg1.setContent("(抄送)您收到一条新的刀具借用消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getId());
            }
         } else {
            msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(type + "_t")) + "id=" + v.toString());
        }
        msg1.setOriginCreateDateTime(DateUtils.strToDate(dateTime, DatePattern.NORM_DATETIME_PATTERN));
        msg1.setCreateByName(userName);
        msg1.setTaskId(null);
        msg1.setProcessInstanceId(delegateExecution.getProcessInstanceId());
        msg1.setUserId(uId);
        msgList.add(msg1);
    }


    private static void handleMsg(DelegateExecution delegateExecution, String title, Object v, List<Msg> msgList, String userName, String dateTime, Long uId, String type) {
        Msg msg1 = new Msg();
        msg1.setTitle(title);
        msg1.setSourceId(v.toString());
        msg1.setSourceType(type);
        msg1.setContent("您收到一条新定额申请单消息");
        if (type.equals("otd_record_ncr")) {
            msg1.setContent("您收到一条及时交付NCR消息");
        }
        if (type.equals("point")) {
            msg1.setContent("您收到一条新非标准定额申请单消息");
        }
        if (type.startsWith("flow_re")) {
            msg1.setContent("您收到一生产资源消息");
        }
        if (type.equals(FlowableCommonEnum.flow_fin_finance_dispatch.getValue())) {
            msg1.setContent("您收到一条新的财务派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_process_performance.getValue())) {
            msg1.setContent("您收到一条新的工装派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_process_craft_dispatch.getValue())) {
            msg1.setContent("您收到一条新的工艺派工申请单消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_quality_craft_dispatch.getValue())) {
            msg1.setContent("您收到一条质量派工消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_fin_cost_ex.getValue())) {
            msg1.setContent("您收到一条异常成本申诉消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_re_knife_move.getValue())) {
            msg1.setContent("您收到一条刀具移库消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else if (type.equals(FlowableCommonEnum.flow_re_knife_transfer.getValue())) {
            msg1.setContent("您收到一条刀具借用消息");
            //转id
            IFlowService flowService = applicationContext.getBean(IFlowService.class);
            Flow flow = flowService.getById(v.toString());
            if (Objects.nonNull(flow)) {
                msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + "&id=" + flow.getTargetDeptId());
            }
        } else {
            msg1.setUrl(FlowableKeyEnum.flowToValues(type + "_t") + CommonUtil.dealUrl(FlowableKeyEnum.flowToValues(type + "_t")) + "id=" + v.toString());
        }
        if (type.startsWith("bomMaterial")) {
            msg1.setContent("您收到一条新材料清单流程消息");
        }
        if (type.startsWith("flow_adjustOrder")) {
            msg1.setContent("您收到一条新的核算派工申请单消息");
        }
        msg1.setOriginCreateDateTime(DateUtils.strToDate(dateTime, DatePattern.NORM_DATETIME_PATTERN));
        msg1.setCreateByName(userName);
        msg1.setTaskId(null);
        msg1.setProcessInstanceId(delegateExecution.getProcessInstanceId());
        msg1.setUserId(uId);
        msgList.add(msg1);
    }






    private static void handleCC(SysRoleMapper roleMapper, SysUserMapper userMapper, List<CcToVo> msgU, String key) {
        SysRole role = new SysRole();
        role.setRoleKey(key);
        List<SysRole> sysRoles = roleMapper.selectRoleList(role);
        SysUser user = new SysUser();
        user.setRoleId(sysRoles.get(0).getRoleId());
        List<SysUser> sysUsers = userMapper.selectAllocatedList(user);
        if (CollectionUtil.isNotEmpty(sysUsers)) {
            sysUsers.stream().forEach(m -> {
                CcToVo ccToVo = new CcToVo();
                ccToVo.setUserId(m.getUserId().toString());
                ccToVo.setUserName(m.getNickName().toString());
                msgU.add(ccToVo);
            });
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext1) throws BeansException {
        applicationContext = applicationContext1;
    }


    static void addRecordPower(List<CcToVo> ccToVos, String processInstanceId, IFlowableRecordPowerService flowableRecordPowerService, String userId) {
        if (StringUtils.isNotBlank(userId)) {
            FlowableRecordPowerQuery criteria = new FlowableRecordPowerQuery();
            criteria.setUserId(Long.parseLong(userId));
            criteria.setProcessIntaneId(processInstanceId);
            if (flowableRecordPowerService.count(WhereEntityTool.invoke(criteria)) == 0) {
                FlowableRecordPower recordPower = new FlowableRecordPower();
                recordPower.setProcessIntaneId(processInstanceId);
                recordPower.setType(FlowableConstant.TJ);
                recordPower.setUserId(Long.parseLong(userId));
                flowableRecordPowerService.save(recordPower);
            }
        }

        if (CollectionUtil.isNotEmpty(ccToVos)) {
            for (CcToVo cc : ccToVos) {
                if (cc != null && StringUtils.isNotBlank(cc.getUserId())) {
                    FlowableRecordPowerQuery criteria = new FlowableRecordPowerQuery();
                    criteria.setUserId(Long.parseLong(cc.getUserId()));
                    criteria.setProcessIntaneId(processInstanceId);
                    if (flowableRecordPowerService.count(WhereEntityTool.invoke(criteria)) == 0) {
                        FlowableRecordPower recordPower = new FlowableRecordPower();
                        recordPower.setProcessIntaneId(processInstanceId);
                        recordPower.setType(FlowableConstant.CC);
                        recordPower.setUserId(Long.parseLong(cc.getUserId()));
                        flowableRecordPowerService.save(recordPower);
                    }
                }
            }
        }
    }

}
